package cn.tworice.admin.web;

import cn.tworice.common.vo.CodeVO;
import cn.tworice.common.entity.Parameter;
import cn.tworice.common.utils.CodeUtil;
import com.alibaba.fastjson.JSON;
import cn.tworice.common.vo.RequestResult;
import cn.tworice.common.vo.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 代码生成
 *
 * @author 二饭[tworice@sina.cn][2022/1/8 20:54]
 */
@RestController
@RequestMapping("admin/codeGeneration")
@CrossOrigin
@Slf4j
public class CodeGeneration {

    @Autowired
    private CodeUtil codeUtil;

    @Autowired
    private cn.tworice.admin.dao.CodeGenerationDao dao;

    @PostMapping("read")
    public RequestResult readFile(String templateName) {
        RequestResult result = new RequestResult();
        String content = codeUtil.readByName(templateName);
        result.appendData("content", content);
        return result;
    }

    @PostMapping("writeVue")
    public RequestResult write(CodeVO codeVO) {
        RequestResult result = new RequestResult();
        boolean isSuccess = codeUtil.buildCodeVue(codeVO);

        if (isSuccess) {
            result.setStatus(new StatusCode(200, "构建Vue页面成功"));
        } else {
            result.setStatus(new StatusCode(204, "构建Vue页面失败"));
        }
        return result;
    }

    /**
     * @param parameters 字段
     * @param tableName 表名称
     * 创建服务端页面及数据库
     * @author 二饭[tworice@sina.cn][2022/1/14 22:30]
     */
    @PostMapping("writeServe")
    public RequestResult write(String parameters,String tableName,String url) {
        RequestResult result = new RequestResult();
        List<Parameter> list=JSON.parseArray(parameters, Parameter.class);
        // 删除ID字段，默认id字段为自增
        for(Parameter item:list){
            if (item.getField().equals("id")) {
                list.remove(item);
                break;
            }
        }
        dao.createNewTable(list,tableName);// 创建表
        log.info("创建数据表成功");
        updateType(list);// 更新字段类型

        // 将表名进行驼峰命名转换
        char[] chars = tableName.toCharArray();
        StringBuilder builder = new StringBuilder();
        chars[0] = (char) (chars[0] - 32);
        for(int i=0;i<tableName.length();i++){
            if(chars[i]=='_'){
                chars[i+1]=(char) (chars[i+1] - 32);
                continue;
            }
            builder.append(chars[i]);
        }
        String entityName = builder.toString();

        // 创建实体类
        boolean success=createEntity(list, entityName);

        // 创建Dao层
        success&=createDao(entityName);

        // 创建Mapper文件
        success&=createMapper(list,entityName,tableName);

        // 创建service文件
        success&=createService(entityName);

        // 创建Client文件
        success&=createClient(entityName,url);
        if(success){
            result.setStatus(new StatusCode(200,"生成服务端文件成功"));
        }else{
            result.setStatus(new StatusCode(204,"生成服务端文件失败"));
        }
        return result;
    }

    /**
     * 创建Client文件
     * @author 二饭[tworice@sina.cn][2022/1/30 18:35]
     */
    public boolean createClient(String name,String url) {
        try{
            StringBuilder builder = new StringBuilder();
            String content = codeUtil.readByName("client");
            content = content.replace("-tworice_name-", name);
            StringBuilder clientHeader = new StringBuilder();
            clientHeader.append("@RestController\r\n");
            clientHeader.append("@RequestMapping(\"");
            clientHeader.append(url);
            clientHeader.append("\")\r\n");
            clientHeader.append("@CrossOrigin\r\n");
            content = content.replace("\")", "\")\r\n");
            content = content.replace("-tworice_client_header-", clientHeader.toString());

            codeUtil.createFile(System.getProperty("user.dir") + "\\src\\main\\java\\cn\\tworice\\client\\web\\" + name + "Client.java", content);
            log.info("生成Client文件成功");
        }catch (Exception exception){
            exception.printStackTrace();
            log.error("生成Client文件失败");
            return false;
        }

        return true;
    }

    /**
     * 创建Service文件
     * @author 二饭[tworice@sina.cn][2022/1/30 18:35]
     */
    public boolean createService(String name) {
        try{
            StringBuilder builder = new StringBuilder();
            String content = codeUtil.readByName("service");
            content = content.replace("-tworice_name-", name);
            int data = content.indexOf("@Service") + 8;
            builder.append(content.substring(0, data));
            builder.append("\r\n");

            int data1 = content.indexOf("@Autowired") + 10;
            builder.append(content.substring(data, data1));
            builder.append("\r\n");
            builder.append(content.substring(data1).trim());
            codeUtil.createFile(System.getProperty("user.dir") + "\\src\\main\\java\\cn\\tworice\\client\\service\\" + name + "Service.java", builder.toString());
            log.info("生成Service文件成功");
        }catch (Exception exception){
            exception.printStackTrace();
            log.error("生成Service文件失败");
            return false;
        }

        return true;
    }

    /**
     * @param name 实体类名称
     * 创建Dao文件
     * @author 二饭[tworice@sina.cn][2022/1/17 20:37]
     */
    public boolean createDao(String name) {
        try{
            StringBuilder builder = new StringBuilder();
            String content = codeUtil.readByName("dao");
            content = content.replace("-tworice_name-", name);
            int data = content.indexOf("@Repository") + 11;
            builder.append(content.substring(0, data));
            builder.append("\r\n");
            builder.append(content.substring(data).trim());
            codeUtil.createFile(System.getProperty("user.dir") + "\\src\\main\\java\\cn\\tworice\\client\\dao\\" + name + "Dao.java", builder.toString());
            log.info("生成Dao文件成功");
        }catch (Exception exception){
            exception.printStackTrace();
            log.error("生成Dao文件失败");
            return false;
        }

        return true;
    }

    /**
     * 创建Mapper文件
     * @param list 字段列表
     * @param entityName 实体类名称
     * @param tableName 数据库表名称
     * @author 二饭[tworice@sina.cn][2022/1/17 20:38]
     */
    public boolean createMapper(List<Parameter> list,String entityName,String tableName) {
        try{
            String content = codeUtil.readByName("mapper");
            content = content.replace("-tworice_name-", entityName);

            // 构建queryList和queryTotal条件语句
            StringBuilder queryList = new StringBuilder();
            StringBuilder queryTotal = new StringBuilder();

            // 构建insertSql
            StringBuilder insertSql = new StringBuilder();
            insertSql.append("INSERT INTO ");
            insertSql.append(tableName);
            insertSql.append("(");

            // 构建insertList SQL
            StringBuilder insertList = new StringBuilder();
            insertList.append("INSERT INTO ");
            insertList.append(tableName);
            insertList.append("(");

            // 构建updateSql
            StringBuilder updateSql = new StringBuilder();
            updateSql.append("UPDATE ");
            updateSql.append(tableName);
            updateSql.append(" SET ");

            // 循环构建sql内容
            for(int i=0;i<list.size();i++){
                insertSql.append(list.get(i).getField());
                insertList.append(list.get(i).getField());

                if(!list.get(i).getField().equals("date")){ // 如果该属性不是日期
                    updateSql.append(list.get(i).getField());
                    updateSql.append("=");
                    updateSql.append("#{");
                    updateSql.append(list.get(i).getField());
                    updateSql.append("}");
                }

                // 构建queryList和queryTotal
                if(list.get(i).getQuery()){ // 判断当前字段是否需要构建查询条件
                    queryList.append("<if test=\"entity."+list.get(i).getField()+"!=null\">");
                    queryTotal.append("<if test=\""+list.get(i).getField()+"!=null\">");
                    if(list.get(i).getQueryType().equals("=")){
                        queryList.append("AND a."+list.get(i).getField()+" = #{entity."+list.get(i).getField()+"}");
                        queryTotal.append("AND "+list.get(i).getField()+" = #{"+list.get(i).getField()+"}");
                    }else if(list.get(i).getQueryType().equals("LIKE")){
                        queryList.append("AND a."+list.get(i).getField()+" LIKE '%${entity."+list.get(i).getField()+"}%'");
                        queryTotal.append("AND "+list.get(i).getField()+" LIKE '%${"+list.get(i).getField()+"}%'");
                    }
                    queryList.append("</if>");
                    queryTotal.append("</if>");

                }

                // 如果当前是列表最后一个时
                if(i==list.size()-1){
                    continue;
                }
                insertSql.append(",");
                insertList.append(",");
                if(!list.get(i).getField().equals("date")){
                    updateSql.append(",");
                }
            }

            // 构建SQL VALUE内容
            insertSql.append(") VALUE(");
            insertList.append(") VALUES");
            insertList.append("<foreach collection=\"list\" separator=\",\" item=\"item\">(");

            for(int i=0;i<list.size();i++){
                insertSql.append("#{");
                insertList.append("#{item.");

                insertSql.append(list.get(i).getField());
                insertList.append(list.get(i).getField());

                if(i==list.size()-1){
                    insertSql.append("}");
                    insertList.append("}");
                    continue;
                }

                insertSql.append("},");
                insertList.append("},");
            }
            insertSql.append(")");
            insertList.append(")</foreach>");

            content = content.replace("-tworice_insert_sql-", insertSql.toString());
            content = content.replace("-tworice_insert_list_sql-", insertList.toString());
            updateSql.append("\r\n WHERE id=#{id}");
            content = content.replace("-tworice_update_sql-", updateSql.toString());
            content = content.replace("-tworice_table_name-", tableName);
            content = content.replace("-tworice_query_list-", queryList.toString());
            content = content.replace("-tworice_query_total-", queryTotal.toString());

            codeUtil.createFile(System.getProperty("user.dir") + "\\src\\main\\resources\\cn\\tworice\\client\\dao\\" + entityName + "Dao.xml", content);
            log.info("生成Mapper文件成功");
        }catch (Exception exception){
            exception.printStackTrace();
            log.error("生成Mapper文件失败");
            return false;
        }

        return true;
    }

    /**
     * 将参数类型从SQL转为Java类型
     * @author 二饭[tworice@sina.cn][2022/1/17 11:45]
     */
    private void updateType(List<Parameter> list){
        list.forEach(item->{
            String type = item.getType();
            if(type.equals("int")){
                item.setType("Integer");
            }else if(type.equals("bigint")){
                item.setType("Long");
            }else if(type.contains("varchar")){
                item.setType("String");
            }else if(type.equals("float")){
                item.setType("Double");
            }
        });
    }

    /**
     * @param name 文件名称
     * @param list 字段名称
     * 创建实体类
     * @author 二饭[tworice@sina.cn][2022/1/17 10:50]
     */
    private boolean createEntity(List<Parameter> list,String name){
        try {
            StringBuilder builder = new StringBuilder();
            String content = codeUtil.readByName("entity");// 通过模板名称读取模板内容
            content = content.replace("-tworice_name-", name);// 替换模板中类名
            // 在注解后加入换行符
            int data = content.indexOf("@Data") + 5;
            builder.append(content.substring(0, data));
            builder.append("\r\n");

            // 找到最后一个花括号，并将花括号前的内容保存起来
            int end = content.lastIndexOf("}");
            builder.append(content.substring(data, end).trim());

            // 在后面加入生成的内容
            list.forEach(item -> {
                builder.append("private ");
                builder.append(item.getType()+" ");
                builder.append(item.getField()+" ");
                builder.append(";");
            });
            builder.append("}");
            codeUtil.createFile(System.getProperty("user.dir") + "\\src\\main\\java\\cn\\tworice\\common\\entity\\code\\" + name + ".java", builder.toString());
            log.info("生成实体类文件成功");
        }catch (Exception exception){
            exception.printStackTrace();
            log.error("生成实体类文件失败");
            return false;
        }
        return true;
    }

    @GetMapping("router")
    public RequestResult getRouter() {
        RequestResult result = new RequestResult();
        result.appendData("router", codeUtil.getRouter());
        return result;
    }
}
